package net.risesoft.api.org;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;

import net.risesoft.entity.Y9Department;
import net.risesoft.entity.Y9Group;
import net.risesoft.entity.Y9Organization;
import net.risesoft.entity.Y9Person;
import net.risesoft.entity.Y9Position;
import net.risesoft.enums.OrgTypeEnum;
import net.risesoft.manager.Y9OrgBaseManager;
import net.risesoft.model.Department;
import net.risesoft.model.Group;
import net.risesoft.model.MessageOrg;
import net.risesoft.model.OrgUnit;
import net.risesoft.model.Organization;
import net.risesoft.model.Person;
import net.risesoft.model.Position;
import net.risesoft.pojo.Y9Result;
import net.risesoft.service.org.Y9DepartmentService;
import net.risesoft.service.org.Y9GroupService;
import net.risesoft.service.org.Y9OrganizationService;
import net.risesoft.service.org.Y9PersonService;
import net.risesoft.service.org.Y9PositionService;
import net.risesoft.util.ModelConvertUtil;
import net.risesoft.y9.Y9LoginUserHolder;
import net.risesoft.y9.json.Y9JsonUtil;
import net.risesoft.y9.pubsub.constant.Y9OrgEventConst;
import net.risesoft.y9public.entity.event.Y9PublishedEvent;
import net.risesoft.y9public.entity.event.Y9PublishedEventSyncHistory;
import net.risesoft.y9public.service.event.Y9PublishedEventService;
import net.risesoft.y9public.service.event.Y9PublishedEventSyncHistoryService;

/**
 * 同步组织事件组件
 *
 * @author dingzhaojun
 * @author qinman
 * @author mengjuhua
 * @date 2022/2/10
 * @since 9.6.0
 */
@Primary
@RestController
@RequestMapping(value = "/services/rest/orgEvent", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class OrgEventApiImpl implements OrgEventApi {

    private final Y9OrgBaseManager y9OrgBaseManager;
    private final Y9DepartmentService orgDepartmentService;
    private final Y9GroupService orgGroupService;
    private final Y9OrganizationService orgOrganizationService;
    private final Y9PersonService orgPersonService;
    private final Y9PositionService orgPositionService;
    private final Y9PublishedEventService y9PublishedEventService;
    private final Y9PublishedEventSyncHistoryService y9PublishedEventSyncHistoryService;

    private OrgUnit getOrgBase(@RequestParam String eventType, @RequestParam String objId) {
        if (StringUtils.isBlank(objId)) {
            return null;
        }
        if (Y9OrgEventConst.RISEORGEVENT_TYPE_ADD_ORGANIZATION.equals(eventType)) {
            Y9Organization org = orgOrganizationService.getById(objId);
            return ModelConvertUtil.convert(org, Organization.class);

        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_ADD_DEPARTMENT.equals(eventType)) {
            Y9Department dept = orgDepartmentService.getById(objId);
            return ModelConvertUtil.convert(dept, Department.class);

        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_ADD_PERSON.equals(eventType)) {
            Y9Person person = orgPersonService.getById(objId);
            return ModelConvertUtil.convert(person, Person.class);

        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_ORGANIZATION.equals(eventType)) {
            Y9Organization org = orgOrganizationService.getById(objId);
            return ModelConvertUtil.convert(org, Organization.class);

        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_DEPARTMENT.equals(eventType)) {
            Y9Department dept = orgDepartmentService.getById(objId);
            return ModelConvertUtil.convert(dept, Department.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_PERSON.equals(eventType)) {
            Y9Person person = orgPersonService.getById(objId);
            return ModelConvertUtil.convert(person, Person.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_ORGANIZATION.equals(eventType)) {
            Y9Organization org = orgOrganizationService.getById(objId);
            return ModelConvertUtil.convert(org, Organization.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_DEPARTMENT.equals(eventType)) {
            Y9Department dept = orgDepartmentService.getById(objId);
            return ModelConvertUtil.convert(dept, Department.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_PERSON.equals(eventType)) {
            Y9Person person = orgPersonService.getById(objId);
            return ModelConvertUtil.convert(person, Person.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_ADD_GROUP.equals(eventType)) {
            Y9Group group = orgGroupService.getById(objId);
            return ModelConvertUtil.convert(group, Group.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_ADD_POSITION.equals(eventType)) {
            Y9Position position = orgPositionService.getById(objId);
            return ModelConvertUtil.convert(position, Position.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_GROUP.equals(eventType)) {
            Y9Group group = orgGroupService.getById(objId);
            return ModelConvertUtil.convert(group, Group.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_UPDATE_POSITION.equals(eventType)) {
            Y9Position position = orgPositionService.getById(objId);
            return ModelConvertUtil.convert(position, Position.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_GROUP.equals(eventType)) {
            Y9Group group = orgGroupService.getById(objId);
            return ModelConvertUtil.convert(group, Group.class);
        } else if (Y9OrgEventConst.RISEORGEVENT_TYPE_DELETE_POSITION.equals(eventType)) {
            Y9Position position = orgPositionService.getById(objId);
            return ModelConvertUtil.convert(position, Position.class);
        }
        return null;
    }

    /**
     * 根据机构id，获取整个组织机构数据
     *
     * @param tenantId 租户id
     * @param organizationId 机构id
     * @return
     * @since 9.6.0
     */
    @Override
    @RequestMapping("/getSyncMap")
    public Y9Result<MessageOrg> getSyncMap(@RequestParam String tenantId, @RequestParam String organizationId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        try {
            HashMap<String, Serializable> dateMap = y9OrgBaseManager.getSyncMap(organizationId, OrgTypeEnum.ORGANIZATION.getEnName(), 1);
            MessageOrg event = new MessageOrg(dateMap, Y9OrgEventConst.RISEORGEVENT_TYPE_SYNC, "ALL", Y9LoginUserHolder.getTenantId());
            return Y9Result.success(event, "获取成功！");
        } catch (Exception e) {
            return Y9Result.failure("获取失败！" + e.getMessage());
        }
    }

    /**
     * 获取全部事件列表
     *
     * @param tenantId 租户id
     * @return
     * @since 9.6.0
     */
    @Override
    @RequestMapping("/listAllEvents")
    public Y9Result<List<MessageOrg>> listAllEvents(@RequestParam String tenantId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9PublishedEvent> list = y9PublishedEventService.listByTenantId(tenantId);
        List<MessageOrg> eventList = new ArrayList<>();
        try {
            for (Y9PublishedEvent event : list) {
                if (StringUtils.isBlank(event.getEntityJson())) {
                    OrgUnit org = getOrgBase(event.getEventType(), event.getObjId());
                    MessageOrg riseEvent = new MessageOrg(Y9JsonUtil.writeValueAsString(org), event.getEventType(), event.getEventTarget(), tenantId);
                    eventList.add(riseEvent);
                } else {
                    MessageOrg riseEvent = new MessageOrg(event.getEntityJson(), event.getEventType(), event.getEventTarget(), tenantId);
                    eventList.add(riseEvent);
                }
            }
            return Y9Result.success(eventList, "获取成功！");
        } catch (Exception e) {
            return Y9Result.failure("获取失败！" + e.getMessage());
        }
    }

    /**
     * 获取当天的事件列表
     *
     * @param tenantId 租户id
     * @param appName 应用名称
     * @return
     * @since 9.6.0
     */
    @Override
    @RequestMapping("/listTodayEvents")
    public Y9Result<List<MessageOrg>> listTodayEvents(@RequestParam String tenantId, @RequestParam String appName) {
        Y9LoginUserHolder.setTenantId(tenantId);

        LocalDateTime timePoint = LocalDateTime.now();
        LocalDateTime start = timePoint.minusDays(1).withHour(23).withMinute(59).withSecond(59);
        Date startDate = Date.from(start.atZone(ZoneId.systemDefault()).toInstant());
        Y9PublishedEventSyncHistory history = y9PublishedEventSyncHistoryService.findByTenantIdAndAppName(tenantId, appName);
        if (history != null) {
            Date lastday = history.getUpdateTime();
            String last = new SimpleDateFormat("yyyy-MM-dd").format(lastday);
            String nowstart = start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            if (!nowstart.equals(last)) {
                startDate = lastday;
            }
        }
        List<Y9PublishedEvent> list = y9PublishedEventService.listByTenantId(tenantId, startDate);
        List<MessageOrg> eventList = new ArrayList<>();
        Map<String, Object> returnMap = new HashMap<>(16);
        returnMap.put("success", true);
        try {
            for (Y9PublishedEvent event : list) {
                if (StringUtils.isBlank(event.getEntityJson())) {
                    OrgUnit org = getOrgBase(event.getEventType(), event.getObjId());
                    MessageOrg riseEvent = new MessageOrg(Y9JsonUtil.writeValueAsString(org), event.getEventType(), event.getEventTarget(), tenantId);
                    eventList.add(riseEvent);
                } else {
                    MessageOrg riseEvent = new MessageOrg(event.getEntityJson(), event.getEventType(), event.getEventTarget(), tenantId);
                    eventList.add(riseEvent);
                }
            }
            y9PublishedEventSyncHistoryService.saveOrUpdate(tenantId, appName);
            returnMap.put("data", eventList);
            return Y9Result.success(eventList, "获取成功！");
        } catch (Exception e) {
            return Y9Result.failure("获取失败！" + e.getMessage());
        }
    }

}
